package ycl.security.handler;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import ycl.common.constants.RedisConstant;
import ycl.common.constants.SecurityConstant;
import ycl.system.entity.SysUser;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * token filter
 *
 * @author ycl
 * @date 2022-03-10 13:30:18
 */
@Component
@Slf4j
public class AuthTokenFilter extends OncePerRequestFilter {

	@Resource
	private StringRedisTemplate stringRedisTemplate;
	@Resource
	private AuthUserDetailProvider authUserDetailProvider;

	/**
	 * token 校验
	 *
	 * @param request
	 * @param response
	 * @param chain
	 * @throws ServletException
	 * @throws IOException
	 */
	@Override
	protected void doFilterInternal(
			HttpServletRequest request,
			HttpServletResponse response,
			FilterChain chain)
			throws ServletException, IOException {

		String token = request.getHeader(SecurityConstant.TOKEN);
		if (StrUtil.isBlank(token) || StrUtil.isBlank(token.trim())) {
			chain.doFilter(request, response);
			return;
		}

		//保存: LoginServiceImpl.login()
		String loginType = request.getHeader(SecurityConstant.LOGIN_TYPE);
		String key = RedisConstant.getLoginUserKey(loginType, token);
		log.info("key ====> {}", key);
		String userVal = stringRedisTemplate.opsForValue().get(RedisConstant.getLoginUserKey(loginType, token));
		log.info("authTokenFilter userVal ============ {}", userVal);
		if (StrUtil.isBlank(userVal)) {
			chain.doFilter(request, response);
			return;
		}

		SysUser user = JSONObject.parseObject(userVal, SysUser.class);
		UserDetails userDetails = authUserDetailProvider.retrieveUser(user.getUsername(), null);
		UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
				userDetails, null, userDetails.getAuthorities());
		authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
		log.info("authenticated user success ======== {} ", userVal);

		chain.doFilter(request, response);
	}
}
